﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using System.IO;
using System.Windows.Forms;

namespace VisualMicroSetupAction
{
    public class VsHelper
    {
        public VsHelper(VsHelperImp.VSVersion eVersion)
        {
            m_imp = new VsHelperImp(eVersion);
        }

        protected VsHelperImp m_imp;
        const String m_VsRegPath = "Software\\Microsoft\\VisualStudio"; // HKEY_CURRENT_USER


        public bool IsInstalled()
        {
            return m_imp.IsInstalled();
        }

        public virtual String GetAddinTargetPath()
        {
            return "";
        }

        public void RunResetAddIn()
        {
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.FileName = "devenv.exe";

            //process.StartInfo.CreateNoWindow = true;
            //process.StartInfo.FileName = commandArray[0];
            process.StartInfo.Arguments = "/resetaddin Visual.Micro.Visual.Studio.Arduino.Helper";
            process.StartInfo.UseShellExecute = true;
            //process.StartInfo.RedirectStandardInput = true;
            //process.StartInfo.RedirectStandardOutput = true;
            //process.StartInfo.RedirectStandardError = true;
            process.Start();
            process.WaitForExit();
            
            
            //devenv.exe
            //"/resetaddin Visual.Micro.Visual.Studio.Arduino.Helper"
        }

        //Visual Studio > Tools > Options > Projects and Solutions > VC++ Project Settings > Extensions To Include
        public void AppendExtensionsToInclude()
        {
            
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\VC"; // HKEY_CURRENT_USER
            String regName = "Extensions To Include";
            String regValue = GetRegValue(regPath, regName);

            String extStr = ";.pde";
            if (!regValue.ToLower().Contains(extStr.ToLower()))
            {
                regValue = regValue + extStr;
                SetRegValue(regPath, regName, regValue, RegistryValueKind.String);
            }
            extStr = ";.ino";
            if (!regValue.ToLower().Contains(extStr.ToLower()))
            {
                regValue = regValue + extStr;
                SetRegValue(regPath, regName, regValue, RegistryValueKind.String);
            }
        }


        public void RemoveExtensionsToInclude()
        {
        
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\VC"; // HKEY_CURRENT_USER
            String regName = "Extensions To Include";
            String regValue = GetRegValue(regPath, regName);

            String extStr = ";.pde";
            if (regValue.ToLower().Contains(extStr.ToLower()))
            {
                String newRegValue = regValue.Replace(extStr, "");
                SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);
            }
            extStr = ";.ino";
            if (regValue.ToLower().Contains(extStr.ToLower()))
            {
                regValue = regValue.Replace(extStr, "");
                SetRegValue(regPath, regName, regValue, RegistryValueKind.String);
            }

        }

        public void AddDefaultEditorsPDE()
        {
            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Default Editors\pde] 
            // Create the subkey if not exist
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString();
            CreateSubkeyIfNotExists(regPath, "Default Editors\\pde");
        
            // Custom
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\Default Editors\\pde"; // HKEY_CURRENT_USER
            String regName = "Custom";
            String newRegValue = "{8B382828-6202-11D1-8870-0000F87579D2}";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);

            
            // Type
            regName = "Type";
            Int32 typeValue = 1;
            SetRegValue(regPath, regName, typeValue, RegistryValueKind.DWord);


            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileExtensionMapping\pde] 
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString();
            CreateSubkeyIfNotExists(regPath, "FileExtensionMapping\\pde");
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\FileExtensionMapping\\pde";

            // (Default)
            regName = "";
            newRegValue = "{8B382828-6202-11D1-8870-0000F87579D2}";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);

            // LogViewID
            regName = "LogViewID";
            newRegValue = "{B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9}";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);

        
        
        
        }

        public void AddDefaultEditorsINO()
        {
            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Default Editors\pde] 
            // Create the subkey if not exist
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString();
            CreateSubkeyIfNotExists(regPath, "Default Editors\\ino");

            // Custom
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\Default Editors\\ino"; // HKEY_CURRENT_USER
            String regName = "Custom";
            String newRegValue = "{8B382828-6202-11D1-8870-0000F87579D2}";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);


            // Type
            regName = "Type";
            Int32 typeValue = 1;
            SetRegValue(regPath, regName, typeValue, RegistryValueKind.DWord);


            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileExtensionMapping\pde] 
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString();
            CreateSubkeyIfNotExists(regPath, "FileExtensionMapping\\ino");
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\FileExtensionMapping\\ino";

            // (Default)
            regName = "";
            newRegValue = "{8B382828-6202-11D1-8870-0000F87579D2}";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);

            // LogViewID
            regName = "LogViewID";
            newRegValue = "{B2F072B0-ABC1-11D0-9D62-00C04FD9DFD9}";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);




        }

        public void RemoveDefaultEditorsPDE()
        {
            return;
            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Default Editors\pde] 
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\Default Editors";
            DeleteSubkeyTreeIfExists(regPath, "pde");

            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileExtensionMapping\pde] 
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\FileExtensionMapping";
            DeleteSubkeyTreeIfExists(regPath, "pde");            
        }

        public void RemoveDefaultEditorsINO()
        {
            return;

            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Default Editors\pde] 
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\Default Editors";
            DeleteSubkeyTreeIfExists(regPath, "ino");

            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileExtensionMapping\pde] 
            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\FileExtensionMapping";
            DeleteSubkeyTreeIfExists(regPath, "ino");
        }

        public void AddLookInFolders(String folderName)
        {
            // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\AutomationOptions\LookInFolders]
            String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString();
            CreateSubkeyIfNotExists(regPath, "AutomationOptions\\LookInFolders");

            regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\AutomationOptions\\LookInFolders"; // HKEY_CURRENT_USER
            String regName = folderName;
            String newRegValue = "";
            SetRegValue(regPath, regName, newRegValue, RegistryValueKind.String);
        }

        public void RemoveLookInFolders(String folderName)
        {
            try
            {
                // [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\AutomationOptions\LookInFolders]
                String regPath = m_VsRegPath + "\\" + m_imp.GetVersionString() + "\\AutomationOptions\\LookInFolders"; // HKEY_CURRENT_USER
                using (RegistryKey hkml = Registry.CurrentUser)
                {
                    using (RegistryKey targetKey = hkml.OpenSubKey(regPath, true))
                    {
                        if (targetKey != null)
                        {
                            targetKey.DeleteValue(folderName, false);
                        }
                    }
                }
            }
            catch (System.Exception)
            { // Do nothing, avoid crash
            }
        }

        private void CreateSubkeyIfNotExists(String parentKeyPath, String subKeyName)
        {
            try
            {
                using (RegistryKey hkml = Registry.CurrentUser)
                {
                    String subKeyPath = parentKeyPath + "\\" + subKeyName;
                    bool bExits = true;
                    using (RegistryKey subKey = hkml.OpenSubKey(subKeyPath))
                    {
                        if (null == subKey) // Not Exist
                        {
                            bExits = false;
                        }
                    }
                    if(!bExits)
                    {
                        using (RegistryKey parentKey = hkml.OpenSubKey(parentKeyPath, true))
                        {
                            if (null != parentKey) // Not Exist
                            {
                                parentKey.CreateSubKey(subKeyName);
                                //MessageBox.Show("Subkey created."); 
                            }
                        }
                    }
                }
            }
            catch (System.Exception)
            { // Do nothing, avoid crash
            }
        }

        private void DeleteSubkeyTreeIfExists(String parentKeyPath, String subKeyName)
        {
            try
            {
                using (RegistryKey hkml = Registry.CurrentUser)
                {
                    String subKeyPath = parentKeyPath + "\\" + subKeyName;
                    bool bExits = true;
                    using (RegistryKey subKey = hkml.OpenSubKey(subKeyPath))
                    {
                        if (null == subKey) // Not Exist
                        {
                            bExits = false;
                        }
                    }
                    if (bExits)
                    {
                        using (RegistryKey parentKey = hkml.OpenSubKey(parentKeyPath, true))
                        {
                            if (null != parentKey) // Not Exist
                            {
                                parentKey.DeleteSubKeyTree(subKeyName);
                                //MessageBox.Show("Subkey deleted."); 
                            }
                        }
                    }
                }
            }
            catch (System.Exception)
            { // Do nothing, avoid crash
            }
        }

        private String GetRegValue(String regPath, String regName)
        {
            String regValue = "";
            try
            {
                using (RegistryKey hkml = Registry.CurrentUser)
                {
                    using (RegistryKey targetKey = hkml.OpenSubKey(regPath, true))
                    {
                        if (targetKey != null)
                        {
                            Object objValue = targetKey.GetValue(regName);
                            if (null != objValue)
                            {
                                regValue = objValue as String;
                            }
                        }
                    }
                }
            }
            catch (System.Exception)
            { // Do nothing, avoid crash
            }

            return regValue;
        }

        private void SetRegValue(String regPath, String regName, object newRegValue, RegistryValueKind valueKind)
        {
            try
            {
                using (RegistryKey hkml = Registry.CurrentUser)
                {
                    using (RegistryKey targetKey = hkml.OpenSubKey(regPath, true))
                    {
                        if (targetKey != null)
                        {
                            targetKey.SetValue(regName, newRegValue, valueKind);
                        }
                    }
                }
            }
            catch (System.Exception)
            { // Do nothing, avoid crash
            }
        }

    }

    public class Vs2005Helper : VsHelper
    {
        public Vs2005Helper()
            : base(VsHelperImp.VSVersion.eV2005)
        {

        }

        public override String GetAddinTargetPath()
        {
            String addinTargetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Visual Studio 2005\Addins");

            DirectoryInfo dirInfo = new DirectoryInfo(addinTargetPath);
            if (!dirInfo.Exists)
            {
                dirInfo.Create();
            }

            return addinTargetPath;
        }
    }

    public class Vs2008Helper : VsHelper
    {
        public Vs2008Helper()
            : base(VsHelperImp.VSVersion.eV2008)
        {

        }

        public override String GetAddinTargetPath()
        {
            String addinTargetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Visual Studio 2008\Addins");

            DirectoryInfo dirInfo = new DirectoryInfo(addinTargetPath);
            if (!dirInfo.Exists)
            {
                dirInfo.Create();
            }

            return addinTargetPath;
        }
    }

    public class Vs2010Helper : VsHelper
    {
        public Vs2010Helper()
            : base(VsHelperImp.VSVersion.eV2010)
        {

        }

        public override String GetAddinTargetPath()
        {
            String addinTargetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Visual Studio 2010\Addins");

            DirectoryInfo dirInfo = new DirectoryInfo(addinTargetPath);
            if (!dirInfo.Exists)
            {
                dirInfo.Create();
            }

            return addinTargetPath;
        }
    }

    public class VsHelperImp
    {
        public VsHelperImp(VSVersion eVersion)
        {
            m_eVersion = eVersion;
        }

        public enum VSVersion
        {
            eV2005,
            eV2008,
            eV2010
        }

        private VSVersion m_eVersion;

        // Check if the external tool key exists to determine if the vs installed.
        public bool IsInstalled()
        {
            String extToolPath = GetExternalToolPath();
            try
            {
                using (RegistryKey hkml = Registry.CurrentUser)
                {
                    using (RegistryKey extToolKey = hkml.OpenSubKey(extToolPath, true))
                    {
                        // By checking the register key for the external tools.
                        if (extToolKey != null)
                            return true;
                    }
                }
            }
            catch (System.Exception)
            { // Do nothing, avoid crash
            }
            return false;
        }

        private String GetExternalToolPath()
        {
            String strVersion = GetVersionString();
            String VsRegPath = "Software\\Microsoft\\VisualStudio"; // HKEY_CURRENT_USER
            //String VsRegPath = "SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio"; //HKEY_LOCAL_MACHINE

            String extToolPath = VsRegPath + "\\" + strVersion + "\\External Tools";

            return extToolPath;
        }

        public String GetVersionString()
        {
            String strVersion = "9.0";
            switch (m_eVersion)
            {
                case VSVersion.eV2005:
                    strVersion = "8.0";
                    break;
                case VSVersion.eV2008:
                    strVersion = "9.0";
                    break;
                case VSVersion.eV2010:
                    strVersion = "10.0";
                    break;
            }

            return strVersion;
        }
    }
}
